package own.stu.jobgib.playown.io.channel;

import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class Demo {

    public static void main(String[] args) throws IOException {

        // fileCopyNormal(new File(filePath("a.txt")), new File(filePath("b.txt")));
        fileCopyWithFileChannelDRead(new File(filePath("a.txt")), new File(filePath("b.txt")));
//        fileCopyWithFileChannel(new File(filePath("a.txt")), new File(filePath("b.txt")));
        System.out.println("done");
    }

    private static String filePath(String fileName) {

        // /D:/own-ler/playown/target/classes/
        String rootPath = Demo.class.getResource("/").getPath();
        String tmpPath = Demo.class.getName().replace(".", "/");
        String substring = tmpPath.substring(0, tmpPath.lastIndexOf("/") + 1);

        // return StringUtils.removeStart(rootPath + substring + fileName, "/");
        return rootPath + substring + fileName;
    }

    /**
     * bufferInputStream 封装了传入的inputStream, 并且包含一个buffer数组，每次read数据时，先判断读取的内容是否大于buffer的大小，如果大于，则直接读取数据，
     * 否则，先将数据读取到buffer中，然后从buffer中读取数据，读取后buffer的对应指针会变动，知道读取到末位，再次将数据填充到buffer中。
     * <p>
     * bufferOutStream 也是类似的，注意一点是，需要调用flush方法，将buffer的数据写入到对应的地方（file,socket等)
     *
     * @param src
     * @param target
     * @throws IOException
     */
    private static void fileCopyNormal(File src, File target) throws IOException {
        BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(src));
        BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(target));

        byte[] bytes = new byte[16];

        int i;

        while ((i = inputStream.read(bytes)) != -1) {
            outputStream.write(bytes, 0, i);
        }

        outputStream.flush();

        outputStream.close();
        inputStream.close();
    }

    private static void fileCopyWithFileChannelDRead(File src, File target) throws IOException {

        FileInputStream inputStream = new FileInputStream(src);
        FileOutputStream outputStream = new FileOutputStream(target);

        // ByteBuffer buffer = ByteBuffer.allocateDirect(16);
        ByteBuffer buffer = ByteBuffer.allocate(16);

        while(inputStream.getChannel().read(buffer) != -1){
            buffer.flip();
            outputStream.getChannel().write(buffer);
            buffer.clear();
        }

        inputStream.close();
        outputStream.close();
    }

    private static void fileCopyWithFileChannel(File src, File target) throws IOException {
        FileOutputStream outputStream = new FileOutputStream(target);
        FileInputStream inputStream = new FileInputStream(src);

        FileChannel inputStreamChannel = inputStream.getChannel();
        FileChannel outputStreamChannel = outputStream.getChannel();

        inputStreamChannel.transferTo(0, inputStreamChannel.size(), outputStreamChannel);

        inputStream.close();
        outputStream.close();
    }
}
